'''
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with self work for additional information
 * regarding copyright ownership.  The ASF licenses self file
 * to you under the Apache License, Version 2.0 (the
 * "License") you may not use self file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http:#www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
'''
from abc import abstractmethod

from base.rdf.Resource import Resource
from base.rdf.ResourceRequiredException import ResourceRequiredException
from base.shared.JenaException import JenaException

#import org.apache.jena.graph.NodeFactory;
#import org.apache.jena.rdf.model.*;
#import org.apache.jena.shared.JenaException;

'''
 * Abstract base class for StaementImpl - pulls up the stuff that doesn't depend
 * on how statements are represented (as S/P/O or as Triples).
'''
class StatementBase:

    # protected final ModelCom model

    # result if
    def __init__(self, model):
        if model is None:
            raise JenaException('model cannot be None')
        self.model = model
    

    # param 
    # result Model
    def getModel(self):
        return self.model
    

    '''
     * replace self StaementImpl [ie the one of which self is the base] with (S,
     * P, n). Answer the StaementImpl. Abstract here to allow methods to be
     * pulled up.
    '''
    # param RDFNode n
    # result abstract StatementImpl
    @abstractmethod
    def replace(self, n):
        pass

    '''
     * Answer the object of self statement as a Literal, or throw a
     * LiteralRequiredException.
    '''
    # param 
    # result abstract Literal
    @abstractmethod
    def getLiteral(self):
        pass

    # param 
    # result abstract Resource
    @abstractmethod
    def getResource(self):
        pass

    # param 
    # result abstract Resource
    @abstractmethod
    def getSubject(self):
        pass

    # param 
    # result abstract Property
    @abstractmethod
    def getPredicate(self):
        pass

    # param 
    # result abstract RDFNode
    @abstractmethod
    def getObject(self):
        pass

    '''
     * @deprecated To be removed: Argument 'wellFormed is ignored
    '''
    # @Deprecated
    # param String s, String lang, boolean wellFormed
    # result StatementImpl
    # @abstractmethod
    # def stringReplace(self, s, lang, wellFormed):
    #     pass
        # return replace(new LiteralImpl(NodeFactory.createLiteral(s, lang, wellFormed), model));


    '''
     * "replace" the Object of self statement with the literal string value _s_.
     * NOTE: self is a convenience function to eliminate the use of a deprecated
     * constructor when data-types are put properly into Jena, it will likely
     * disappear.
    '''
    # param String s
    # result StatementImpl
    @abstractmethod
    def stringReplace(self, s):
        pass
        # return stringReplace(s, "", false);

    # param boolean o
    # result Statement
    def changeLiteralObject(self, o):
        return self.changeObject(self.model.createTypedLiteral(o))
    

    # param String o
    # result Statement
    def changeObjectWithStr(self, o):
        return self.stringReplace(str(o))

    # param RDFNode o
    # result Statement
    def changeObject(self, o):
        return self.replace(o)


    # param 
    # result boolean
    def getBoolean(self):
        return self.getLiteral().getBoolean()


    # param 
    # result byte
    def getByte(self):
        pass

    # param
    # result int
    def getInt(self):
        return self.getLiteral().getInt()


    # param 
    # result long
    def getLong(self):
        return self.getInt()

    # param 
    # result char
    def getChar(self):
        return self.getString()


    # param 
    # result float
    def getFloat(self):
        return self.getLiteral().getFloat()

    # param
    # result double
    def getDouble(self):
        return self.getFloat()

    # param 
    # result String
    def getString(self):
        return self.getLiteral().getLexicalForm()


    '''
     * utility: check that node is a Resource, throw otherwise
    '''
    # param RDFNode n
    # result Resource
    def mustBeResource(self, n):
        if isinstance(n, Resource):
            return n
        raise ResourceRequiredException(n)

    # param
    # result String
    def getLanguage(self):
        return self.getLiteral().getLanguage()


    '''
     * Answer a string describing self Statement in a vaguely pretty way, with the
     * representations of the subject, predicate, and object in that order.
    '''
    # @Override
    # param 
    # result String
    def toString(self):
        return "[" + self.getSubject().toString() + ", " + self.getPredicate().toString() + ", " + self.objectString(self.getObject()) + "]"

    '''
     * Answer a string describing <code>object</code>, quoting it if it is a literal.
    '''
    # param RDFNode object
    # result String
    def objectString(self, obj):
        return obj.asNode().toString(None, True)


